package com.ec.auth.config;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.TypeFactory;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
import com.alibaba.fastjson.parser.ParserConfig;
import org.springframework.util.Assert;

import java.nio.charset.Charset;

/**
 * Redis使用FastJson序列化
 * 这定义了一个名为 FastJson2JsonRedisSerializer 的公共类，并实现了 RedisSerializer 接口。
 * T 是一个类型参数，用于表示要序列化和反序列化的对象类型
 * @author ec
 */
public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T> {

    // 这定义了一个静态常量 DEFAULT_CHARSET，并将其设置为 UTF-8 字符集
    public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");

    // 在类加载时，会执行这个静态代码块。
    // 它通过 ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
    // 来启用 FastJson 的自动类型支持
    static {
        ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
    }

    // objectMapper 是一个私有成员变量，用于处理 JSON 序列化和反序列化
    @SuppressWarnings("unused")
    private ObjectMapper objectMapper = new ObjectMapper();

    // clazz 是一个表示要序列化和反序列化的对象类型的成员变量
    private Class<T> clazz;


    // 构造函数/构造方法
    public FastJson2JsonRedisSerializer(Class<T> clazz) {
        super();
        this.clazz = clazz;
    }

    /**
     * 这个方法实现了 RedisSerializer 接口的 serialize 方法。
     * @param t
     * @return
     * @throws SerializationException
     */
    @Override
    public byte[] serialize(T t) throws SerializationException {
        // 它检查要序列化的对象是否为 null，如果是，则返回一个空字节数组。
        if (t == null) {
            return new byte[0];
        }
        // 否则，它使用 FastJson 将对象序列化为 JSON 字符串，并将其编码为指定的字符集字节数组。
        return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
    }


    /**
     * 这个方法实现了 RedisSerializer 接口的 deserialize 方法。
     * @param bytes
     * @return
     * @throws SerializationException
     */
    @Override
    public T deserialize(byte[] bytes) throws SerializationException {
        // 它检查要反序列化的字节数组是否为空或长度为 0， 如果是，则返回 null。
        if (bytes == null || bytes.length <= 0) {
            return null;
        }
        // 否则，它将字节数组解码为字符串，并使用 FastJson 将其反序列化为指定类型的对象
        String str = new String(bytes, DEFAULT_CHARSET);
        return JSON.parseObject(str, clazz);
    }

    // 这个方法用于设置自定义的 ObjectMapper 对象。
    public void setObjectMapper(ObjectMapper objectMapper) {
        // 它通过 Assert.notNull 方法确保传递的 objectMapper 不为 null
        Assert.notNull(objectMapper, "'objectMapper' must not be null");
        this.objectMapper = objectMapper;
    }

    protected JavaType getJavaType(Class<?> clazz) {
        return TypeFactory.defaultInstance().constructType(clazz);
    }
}
